/* arch/x86/init/head64.S 
 * 
 * Copyright (C) 2021, 2022 intirain. 
 * 
 * This file is part of evx. 
 * 
 * evx is free software: you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation, either version 3 of the License, or 
 * (at your option) any later version. 
 * 
 * evx is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with evx. If not, see <https://www.gnu.org/licenses/>
 */ 




.code64


.globl _start

_start:
	/* we are now in the long-mode, just 
	 * do some initializes, and call main */

	call setup_stack
	call init_gdt
	call init_idt
	call setup_paging

	movq $0xffff800000000000, %rax
	leaq 1f(%rip), %rcx

	orq %rcx, %rax

	pushq %rax

	movq $0xffff800000000000, %rax
	leaq init(%rip), %rcx

	orq %rcx, %rax

	pushq %rax

	retq

1:	hlt
	jmp 1b


init_gdt:
	lgdt gdt_descr(%rip)

	movq $0x10, %rax

	movq %rax, %ds
	movq %rax, %es
	movq %rax, %fs
	movq %rax, %gs
	movq %rax, %ss

	ret

setup_stack:
	/* `setup_paging` used 0~0x80000, so we must 
	 * find a new space for stack (old stack at 0x7c00). 
	 * 
	 * but sadly, we can't use address above 1048576 because 
	 * the `arch_mm_init` will use them as the page and zone 
	 * structures. so, would you like to use someplace in 
	 * .data? :-) */

	movq (%rsp), %rax

	movq $0x90000, %rsp

	jmp *%rax


setup_paging:
	/* map 0-1g memory (512 entries), 
	 * use memory from 0x2000 ~ 0x3000 */

	movq $0x2000, %rdi
	movq $0x83, %rax

	cld

spl: 	stosq
	addq $2097152, %rax

	cmpq $0x3000, %rdi
	jbe spl

	xorq %rax, %rax
	movq %rax, %cr3

	ret

init_idt:
	leaq default_int_handler(%rip), %rdx
	movq $(8 << 16), %rax
	
	movw %dx, %ax
	
	/* 0x8e: interrupt gate */
	movq $(0x8e00 << 32), %rcx
	addq %rcx, %rax

	movl %edx, %ecx
	
	shrl $16, %ecx
	shlq $48, %rcx
	
	addq %rcx, %rax
	shrq $32, %rdx
	
	movq $256, %rcx
	leaq idt(%rip), %rdi

rsidt: 	movq %rax, (%rdi)
	movq %rdx, 8(%rdi)
	addq $16, %rdi

	decq %rcx
	jnz rsidt

	lidt idt_descr(%rip)

	ret

default_int_handler:
	incq 0xb8000
	iretq

.globl ret_intr

ret_intr:
	popq %rax
	movq %rax, %gs

	popq %rax
	movq %rax, %fs

	popq %rax
	movq %rax, %es
	
	popq %rax
	movq %rax, %ds

	popq %r15
	popq %r14
	popq %r13
	popq %r12
	popq %r11
	popq %r10
	popq %r9
	popq %r8

	popq %rdi
	popq %rsi
	popq %rbp
	popq %rdx
	popq %rbx
	popq %rcx
	popq %rax

/* errrcode */
	addq $8, %rsp

	iretq


.globl __stack_chk_fail
.globl die

__stack_chk_fail:
die:
	hlt
	jmp __stack_chk_fail

.data

.align 16

.globl gdt

gdt:	.quad 0x0000000000000000
	.quad 0x0020980000000000
	.quad 0x0000920000000000


.globl gdt_descr

gdt_descr:
	.word . - gdt
	.quad gdt


.globl idt

.align 16

idt: 	.fill 512, 8, 0

.globl idt_descr 

idt_descr:
	.word . - idt
	.quad idt


.data


